package com.sghj.config.filter;



import com.sghj.utils.StringUtils;
import com.sghj.utils.sql.SqlUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * XSS过滤处理
 * 
 * @author xrx
 */
@Slf4j
public class SqlHttpServletRequestWrapper extends HttpServletRequestWrapper
{
    /**
     * 构造请求对象
     *
     * @param request
     */
    public SqlHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    /**
     * 获取头部参数
     *
     * @param v 参数值
     */
    @Override
    public String getHeader(String v) {
        String header = super.getHeader(v);
        if (header == null || "".equals(header)) {
            return header;
        }
        return sqlFilter(header);
    }

    /**
     * 获取参数
     *
     * @param v 参数值
     */
    @Override
    public String getParameter(String v) {
        String param = super.getParameter(v);
        if (param == null || "".equals(param)) {
            return param;
        }
        return sqlFilter(param);
    }

    /**
     * 获取参数值
     *
     * @param v 参数值
     */
    @Override
    public String[] getParameterValues(String v) {
        String[] values = super.getParameterValues(v);
        if (values == null) {
            return values;
        }

        // 富文本内容不过滤
        if ("remarks".equals(v)) {
            return values;
        }

        int length = values.length;
        String[] resultValues = new String[length];
        for (int i = 0; i < length; i++) {
            // 过滤特殊字符
            resultValues[i] = sqlFilter(values[i]);
            if (!(resultValues[i]).equals(values[i])) {
                log.debug("SQL注入过滤器 => 过滤前：{} => 过滤后：{}", values[i], resultValues[i]);
            }
            SqlUtil.filterKeyword(values[i]);
        }
        return resultValues;
    }

    @Override
    public ServletInputStream getInputStream() throws IOException
    {
        // 非json类型，直接返回
        if (!isJsonRequest())
        {
            return super.getInputStream();
        }

        // 为空，直接返回
        String json = IOUtils.toString(super.getInputStream(), "utf-8");
        if (StringUtils.isEmpty(json))
        {
            return super.getInputStream();
        }

        SqlUtil.filterKeyword(json);

        // sql过滤
        //json = EscapeUtil.clean(json).trim();
        byte[] jsonBytes = json.getBytes("utf-8");
        final ByteArrayInputStream bis = new ByteArrayInputStream(jsonBytes);
        return new ServletInputStream()
        {
            @Override
            public boolean isFinished()
            {
                return true;
            }

            @Override
            public boolean isReady()
            {
                return true;
            }

            @Override
            public int available() throws IOException
            {
                return super.available();
            }

            @Override
            public void setReadListener(ReadListener readListener)
            {
            }

            @Override
            public int read() throws IOException
            {
                return bis.read();
            }
        };
    }

    /**
     * 是否是Json请求
     *
     */
    public boolean isJsonRequest()
    {
        String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
        return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
    }
    /**
     * 预编译SQL过滤正则表达式
     */
    private Pattern sqlPattern = Pattern.compile(
            "(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|(\\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)",
            Pattern.CASE_INSENSITIVE);

    /**
     * SQL过滤
     *
     * @param v 参数值
     * @return
     */
    private String sqlFilter(String v) {
        if (v != null) {
            String resultVal = v;
            Matcher matcher = sqlPattern.matcher(resultVal);
            if (matcher.find()) {
                resultVal = matcher.replaceAll("");
            }
            if (!resultVal.equals(v)) {
                return "";
            }
            return resultVal;
        }
        return null;
    }
}